#include "unixHeader.h"
#include "hash.h"
#include <iostream>

#include <workflow/WFFacilities.h>
#include <workflow/MySQLResult.h>
#include <wfrest/HttpServer.h>



using namespace std;
using namespace wfrest;

static WFFacilities::WaitGroup waitGroup(1);

void test0()
{
    HttpServer server;

    server.GET("/file/upload", [](const HttpReq * , HttpResp * resp){
        resp->File("./static/view/index.html");
    });

    server.GET("/file/upload/success", [](const HttpReq * , HttpResp * resp){
        resp->String("upload success");
    });

    server.POST("/file/upload", [](const HttpReq * req, 
        HttpResp * resp,
        SeriesWork * series){
        if(req->content_type() == MULTIPART_FORM_DATA) {
            //获取文件的信息
            auto & formMap = req->form();
            string filename = formMap["file"].first;
            string content = formMap["file"].second;
            cout << "filename:" << filename << endl;
            cout << "content'size:" << content.size() << endl;

            //将文件内容写入本地文件
            string filepath = "./tmp/" + filename;
            mkdir("./tmp", 0755);
            int fd = open(filepath.c_str(), O_CREAT|O_RDWR, 0755);
            if(fd < 0) {
                perror("open");
                return;
            }
            write(fd, content.c_str(), content.size());
            close(fd);

            //获取hash值
            Hash hash(filepath);
            string filehash = hash.sha1();
            //更新数据库的操作
            
            string mysqlurl("mysql://root:1234@localhost");
            auto mysqlTask = WFTaskFactory::create_mysql_task(
                mysqlurl, 0,
                [resp](WFMySQLTask * mysqltask){
                    auto mysqlresp = mysqltask->get_resp();
                    int state = mysqltask->get_state();
                    int error = mysqltask->get_error();
                    if(state != WFT_STATE_SUCCESS) {
                        printf("error: %s\n", WFGlobal::get_error_string(state, error));
                        return;
                    }

                    //语法错误
                    if(mysqlresp->get_packet_type() == MYSQL_PACKET_HEADER_ERROR) {
                        printf("error_code: %d, msg: %s\n",
                            mysqlresp->get_error_code(),
                            mysqlresp->get_error_msg().c_str());
                        resp->set_status_code("500");
                        return;
                    }

                    using namespace protocol;
                    //通过迭代器访问结果
                    MySQLResultCursor cursor(mysqlresp);
                    if(cursor.get_affected_rows() == 1) {
                        //重定向
                        resp->set_status_code("302");
                        resp->headers["Location"] = "/file/upload/success";
                    } else {
                        resp->set_status_code("500");
                    }
                });
            string filesizestr = to_string(content.size());
            string sql = "INSERT INTO cloudisk.tbl_file(`file_sha1`, `file_name`,`file_size`, `file_addr`, `status`) VALUES (";
            sql += "'" + filehash + "', ";
            sql += "'" + filename + "', ";
            sql += "'" + filesizestr + "',";
            sql += "'" + filepath + "',";
            sql += "0)";
            cout << "sql:\n" <<  sql << endl;
            mysqlTask->get_req()->set_query(sql);
            series->push_back(mysqlTask);
        }
    });

    server.GET("/file/download", [](const HttpReq * req, HttpResp * resp){
        auto querylist = req->query_list();
        string filename = querylist["filename"];
        string filehash = querylist["filehash"];
        string filesizestr = querylist["filesize"];
        int filesize = stoi(filesizestr);
        cout << "filesize:" << filesize << endl;

        //方案二: 下载文件 //用重定向
        resp->headers["Location"] = "http://192.168.30.128:8080/" + filename;
        resp->set_status_code("302");
        
        //方案一:
        /* string filepath = "./tmp/" + filename; */
        /* int fd = open(filepath.c_str(), O_RDONLY); */
        /* if(fd < 0) { */
        /*     perror("open"); */
        /*     return; */
        /* } */
        /* //读取文件 */
        /* char * buff  = new char[filesize+1](); */
        /* int ret = read(fd, buff, filesize); */
        /* close(fd); */
        /* //设置响应 */
        /* resp->append_output_body(buff, ret); */
        /* resp->headers["Content-Type"] = "application/octet-stream"; */
        /* resp->headers["Content-Disposition"] = "attachment;filename=" + filename; */
        /* delete [] buff; */
    });

    if(server.track().start(8888) == 0) {
        server.list_routes();
        waitGroup.wait();
        server.stop();
    } else {
        printf("server cannnot start\n");
    }
}


int main()
{
    test0();
    return 0;
}

